package com.sit.library.config;

import com.sit.library.entity.bean.Account;
import com.sit.library.entity.bean.RestBean;
import com.sit.library.entity.vo.response.AuthorizeVO;
import com.sit.library.filter.JwtAuthorizeFilter;
import com.sit.library.service.AuthorizeService;
import com.sit.library.utils.JwtUtils;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.io.PrintWriter;

// Spring Security 配置类
@Configuration
public class SecurityConfiguration {

    @Resource
    JwtUtils jwtUtils;

    @Resource
    JwtAuthorizeFilter jwtAuthorizeFilter;

    @Resource
    AuthorizeService authorizeService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                // 角色权限管理
                .authorizeHttpRequests(conf -> conf
                        .requestMatchers("/api/auth/**").permitAll()
                        .requestMatchers("/api/user/**").hasAnyRole("user", "admin")
                        .requestMatchers("/api/admin/**").hasRole("admin")
                        .anyRequest().authenticated()
                )
                // 登录设置
                .formLogin(conf -> conf
                        .loginProcessingUrl("/api/auth/login")
                        // 登录失败处理
                        .failureHandler((request, response, exception) -> {
                            response.setContentType("application/json;charset=utf-8");
                            response.getWriter().write(RestBean.failure(401, exception.getMessage()).asJsonString());
                        })
                        // 登录成功处理
                        .successHandler((request, response, authentication) -> {
                            response.setContentType("application/json; charset=utf-8");
                            User user = (User) authentication.getPrincipal();
                            Account account = authorizeService.findByUsername(user.getUsername());
                            String token = jwtUtils.createJwt(user, account.getId(), account.getName());
                            AuthorizeVO vo = new AuthorizeVO();
                            vo.setExpires(jwtUtils.expireTime());
                            vo.setToken(token);
                            vo.setUsername(account.getName());
                            vo.setRole(account.getRole());
                            response.getWriter().write(RestBean.success(vo).asJsonString());
                        })
                )
                // 登出设置
                .logout(conf -> conf
                        .logoutUrl("/api/auth/logout")
                        .logoutSuccessHandler((request, response, authentication) -> {
                            response.setContentType("application/json; charset=utf-8");
                            String authorization = request.getHeader("Authorization");
                            if (jwtUtils.invalidateJwt(authorization)) {
                                response.getWriter().write(RestBean.success().asJsonString());
                            } else {
                                response.getWriter().write(RestBean.failure(400, "退出登录失败").asJsonString());
                            }
                        })
                )
                .exceptionHandling(conf -> conf
                        // 未登录处理
                        .authenticationEntryPoint((request, response, exception) -> {
                            response.setContentType("application/json; charset=utf-8");
                            response.getWriter().write(RestBean.failure(401, exception.getMessage()).asJsonString());
                        })
                        // 未授权处理
                        .accessDeniedHandler((request, response, exception) -> {
                            response.setContentType("application/json; charset=utf-8");
                            response.getWriter().write(RestBean.failure(403, exception.getMessage()).asJsonString());
                        })
                )
                // 关闭 csrf
                .csrf(AbstractHttpConfigurer::disable)
                // session 改为无状态
                .sessionManagement(conf -> conf
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                // 添加 JWT 验证过滤器
                .addFilterBefore(jwtAuthorizeFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }
}
